<!DOCTYPE html>
<title>Custom Elements: Create an element when definition is non-null and synchronous flag not set</title>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="resources/custom-elements-helpers.js"></script>
<body>
<script>
'use strict';

// Create an element
// https://dom.spec.whatwg.org/#concept-create-element
// 6. If definition is non-null, then:
// 6.2. If the synchronous custom elements flag is not set:

(() => {
  // customElements.define() upgrades existing elements
  // with synchronous flag unset.
  test_with_window(w => {
    create_element_and_upgrade(w);
  }, 'define() should upgrade existing elements');

  function create_element_and_upgrade(w) {
    let document = w.document;
    let element = document.createElement('a-a');
    document.body.appendChild(element);
    assert_false('is_custom_constructed' in element, 'Constructor should not run before define()');
    define(w);
    assert_true(element.is_custom_constructed, 'Constructor should run after define()');
    return element;
  }

  function define(w) {
    w.customElements.define('a-a', class extends w.HTMLElement {
      constructor() { super(); this.is_custom_constructed = true; }
    });
  }

  // The "clone a node" concept is async.
  // https://dom.spec.whatwg.org/#concept-node-clone
  test_with_window(w => {
    let element = create_element_and_upgrade(w);
    let clone = element.cloneNode();
    assert_true(clone.is_custom_constructed);
  }, 'cloneNode() should run custom constructor');

  // importNode() uses the same "clone a node" conecpt to clone the node.
  test_with_window(w => {
    define(w);
    let document = w.document;
    let another_document = document.implementation.createHTMLDocument();
    let element_in_another_document = another_document.createElement('a-a');
    let imported = document.importNode(element_in_another_document);
    assert_true(imported.is_custom_constructed);
  }, 'importNode() should run custom constructor');

  // innerHTML/outerHTML setters use the fragment parser.
  // https://w3c.github.io/DOM-Parsing/#dom-element-innerhtml
  // Synchronous flag is unset if HTML fragment parsing algorithm.
  // https://html.spec.whatwg.org/multipage/syntax.html#create-an-element-for-the-token
  test_with_window(w => {
    define(w);
    let document = w.document;
    let fragment = document.createElement('div');
    document.body.appendChild(fragment);
    fragment.innerHTML = '<a-a></a-a>';
    assert_true(fragment.children[0].is_custom_constructed);
  }, 'innerHTML setter should run custom constructor');

  test_with_window(w => {
    define(w);
    let document = w.document;
    let fragment = document.createElement('div');
    document.body.appendChild(fragment);
    fragment.outerHTML = '<a-a></a-a>';
    assert_true(document.body.children[0].is_custom_constructed);
  }, 'outerHTML setter should run custom constructor');
})();
</script>
</body>
